package io.renren.modules.workflow.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpStatus;
import io.renren.common.utils.AjaxResult;
import io.renren.modules.sys.entity.SysUserEntity;
import io.renren.modules.workflow.dao.ActBusModelDefinitionMapper;
import io.renren.modules.workflow.dao.ActBusModuleConnectionMapper;
import io.renren.modules.workflow.dao.ActBusWorkflowDataMapper;
import io.renren.modules.workflow.entity.ActBusModelDefinition;
import io.renren.modules.workflow.entity.ActBusWorkflowData;
import io.renren.modules.workflow.entity.dto.ActBusProcessInstanceStartParams;
import io.renren.modules.workflow.enums.ActBusDeployStatusEnum;
import io.renren.modules.workflow.enums.ActBusWorkFlowStatusEnum;
import io.renren.modules.workflow.enums.ActOperationTypeEnum;
import io.renren.modules.workflow.service.IActBusArchivesDataService;
import io.renren.modules.workflow.service.IActBusModelDefinitionService;
import io.renren.modules.workflow.service.IActBusProcessInstanceService;
import io.renren.modules.workflow.utils.ActBusActivitiUtils;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @Desc 流程实例服务类实现
 * @Author landlord
 * @Date 2021/7/26 18:08
 */
@Service
public class ActBusProcessInstanceServiceImpl implements IActBusProcessInstanceService {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private IActBusModelDefinitionService actBusModelDefinitionService;
    @Autowired
    private ActBusWorkflowDataMapper actBusWorkflowDataMapper;
    @Autowired
    private IActBusArchivesDataService actBusArchivesDataService;
    @Autowired
    private ActBusActivitiUtils actBusActivitiUtils;
    @Autowired
    private ActBusModuleConnectionMapper actBusModuleConnectionMapper;
    @Autowired
    private ActBusModelDefinitionMapper actBusModelDefinitionMapper;
    /**
     * @Desc: 启动一个流程实例对象业务
     * @auther: landlord 开启
     * @date: 2021/7/26 18:09
     * @todo 需要完善的地方：1、流程发起时 需要读取XML获取下一个环节设置的审批人信息；
     * @return:
     */
    @Override
    @Transactional
    public AjaxResult startWorkFlowProcess(ActBusProcessInstanceStartParams actBusProcessInstanceStartParams) {
        //判断所需要的参数
//        if(StrUtil.isEmpty(actBusProcessInstanceStartParams.getAdmdId())){
//            return AjaxResult.error("流程启动失败:没有找到流程ID参数");
//        }
//        //根据流程ID获取流程信息
//        ActBusModelDefinition actBusModelDefinition =
//                actBusModelDefinitionService.selectActBusModelDefinitionById(
//                        actBusProcessInstanceStartParams.getAdmdId());
//        if(actBusModelDefinition==null){
//            return AjaxResult.error("流程启动失败:流程对象未找到");
//        }
//        if(StrUtil.isEmpty(actBusProcessInstanceStartParams.getFormJson())){
//            return AjaxResult.error("流程启动失败:表单信息未找到");
//        }
//        //定义常用参数变量
//        String userId = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUsername();
//        String userNickName = SecurityUtils.getLoginUser().getUser().getNickName();
//        String deptId = SecurityUtils.getLoginUser().getUser().getDept().getDeptId().toString();
//        String deptName = SecurityUtils.getLoginUser().getUser().getDept().getDeptName();
//        String businessType = actBusModelDefinition.getAbmdType();
//
//        *//**启动流程实例业务**//*
//        //设置流程title所需参数
//        Map<String,Object> params = new HashMap<>();
//        params.put("businessType",businessType);
//
//        //根据表单插入流程业务数据 获取业务ID
//        ActBusWorkflowData abwfd = new ActBusWorkflowData(
//                actBusModelDefinition.getAbmdDeployId(),
//                "","",actBusModelDefinition.getAbmdType(),
//                ActBusBusinessUtils.setWordFlowTitle(params),
//                actBusProcessInstanceStartParams.getFormJson(), userId, userNickName,deptId, deptName,
//                "", null, null
//        );
//        abwfd.setDeptId(Long.valueOf(deptId));
//        abwfd.setCreateBy(SecurityUtils.getUsername() + "(" + SecurityUtils.getLoginUser().getUser().getNickName() + ")");
//        abwfd.setCreateTime(DateUtils.getNowDate());
//        abwfd.setProcessNo(actBusProcessInstanceStartParams.getProcessNo());
//
//        //插入业务数据
//        if(!ActBusinessTypeEnum.UTILIZE.getKey().equalsIgnoreCase(businessType)) {
//            if (StringUtils.isEmpty(actBusProcessInstanceStartParams.getTableName()) ||
//                    StringUtils.isEmpty(actBusProcessInstanceStartParams.getBusType()) ||
//                    StringUtils.isEmpty(actBusProcessInstanceStartParams.getCategoryId()) ||
//                    actBusProcessInstanceStartParams.getParamIds() == null) {
//                return AjaxResult.error("参数获取失败");
//            }
//        }
//        actBusWorkflowDataMapper.insertActBusWorkflowData(abwfd);
//        if(abwfd.getAbwdId()==null){
//            return AjaxResult.error("获取流程单据失败");
//        }
//        // 业务数据重新赋值
//        ActBusArchivesData actBusArchivesData = new ActBusArchivesData();
//        actBusArchivesData.setTableName(actBusProcessInstanceStartParams.getTableName());
//        actBusArchivesData.setBusType(actBusProcessInstanceStartParams.getBusType());
//        actBusArchivesData.setCategoryId(actBusProcessInstanceStartParams.getCategoryId());
//        actBusArchivesData.setBusinessType(businessType);
//        actBusArchivesData.setParamIds(actBusProcessInstanceStartParams.getParamIds());
//        actBusArchivesData.setUsingMap(actBusProcessInstanceStartParams.getUsingMap());
//        actBusArchivesData.setAbwdId(abwfd.getAbwdId());
//        //新增档案业务数据关联流程数据
//        actBusArchivesDataService.insertActBusArchivesData(actBusArchivesData);
//        //获取业务ID放入流程
//        String businessKey = abwfd.getAbwdId().toString();
//        //先解析发起人填写的表单信息 作为流程变量
//        Map<String,Object> varsForm = ActBusBusinessUtils.parseWorkFlowFormJson(actBusProcessInstanceStartParams.getFormJson());
//        //设置流程启动流程变量
//        Set<String> varsList = actBusActivitiUtils.getBpmnXmlAllVariables(actBusModelDefinition.getAbmdXml());
//        Map<String,Object> vars = new HashMap<>();
//        if(varsList!=null && varsList.size()>0){
//            varsList.forEach(key->{
//                if(!key.equals(ActBusSpecialBusinessEnum.APPROVAL.getKey())){
//                    vars.put(key,varsForm.get(key));
//                }
//            });
//        }
//        //启动流程实例
//        Authentication.setAuthenticatedUserId(userId);//设置开始审批人
//        ProcessInstance processInstance =
//                runtimeService.startProcessInstanceByKey("WF-"+ actBusProcessInstanceStartParams.getAdmdId(),
//                                                            businessKey, vars);
//        //根据部署流程获取等待执行的任务
//        Task task = taskService.createTaskQuery()
//                .processInstanceId(processInstance.getId())
//                .singleResult();
//        //如果没有任务则流程结束了
//        if(task!=null){
//            //设置流程任务变量
//            vars.put("firstNodeId",task.getTaskDefinitionKey());
//            taskService.setVariables(task.getId(),vars);
//            //更新业务数据
//            abwfd.setAbwdDefineId(processInstance.getProcessDefinitionId());
//            abwfd.setAbwdInstanceId(processInstance.getId());
//            abwfd.setAbwdTaskId(task.getId());
//            abwfd.setAbwdWorkflowStatus(ActBusWorkFlowStatusEnum.STAGING.getKey());//暂存
//            actBusWorkflowDataMapper.updateActBusWorkflowData(abwfd);
//        }
        AjaxResult ajaxResult = new AjaxResult();
        ajaxResult.put("code", HttpStatus.HTTP_OK);
        ajaxResult.put("msg","流程启动成功");
        //ajaxResult.put("data",task.getId());
        //ajaxResult.put("abwdId",businessKey);
        return ajaxResult;
    }

    /**
     * @Desc: 根据当前任务获取下一个任务办理人集合
     * @auther: landlord
     * @date: 2021/8/9 20:22
     * @return:
     */
   @Override
   public AjaxResult nextTaskHandlePeople(String taskId){
       //根据任务ID获取当前任务对象
      Task task = actBusActivitiUtils.getCurrentTaskOrCurrentUserTaks(taskId,null);
      if(task==null){
         return AjaxResult.error("当前任务已完结或者用户没有权限");
      }
      List<UserTask> userTaskList = new ArrayList<>();
      //得到当前任务流程变量
      Map<String,Object> taskVariables = actBusActivitiUtils.getTaskVariables(taskId);
      //得到流程过程对象
      Process process = actBusActivitiUtils.getProcess(task.getProcessDefinitionId());
      //得到走向
      Collection<FlowElement> flowElements = process.getFlowElements();
      //得到当前走向
      FlowElement flowElement = actBusActivitiUtils.getFlowElementById(task.getTaskDefinitionKey(),flowElements);
      actBusActivitiUtils.getNextNodeRecur(flowElements,flowElement,taskVariables,userTaskList);
      if(userTaskList!=null && userTaskList.size()>0){
          //这里不考虑多个节点问题 就算有多个 默认取第一个
          UserTask userTask = userTaskList.get(0);
          if(userTask.getName().equals("_END_")){ //表示下一个环节为结束
              return AjaxResult.success("end");
          }
          //得到环节处理人 集合
          Map<String,Object> resMap = new HashMap<>();
          String userId = userTask.getAssignee();
          if(StrUtil.isNotEmpty(userId)){
              SysUserEntity sysUser = actBusModuleConnectionMapper.selectUserByUserNameAct(userId);
              resMap.put("assignee",sysUser);
          }
          //得到环节处理角色ID
          String roleId = (userTask.getCandidateGroups()!=null && userTask.getCandidateGroups().size()>0)?userTask.getCandidateGroups().get(0):"";
          if(StrUtil.isNotEmpty(roleId)){
              List<SysUserEntity> resRolsUserList =
                      actBusModuleConnectionMapper.selectRoleToUsersByRoleIdAct(Long.parseLong(roleId));
              if(resRolsUserList!=null && resRolsUserList.size()>0){
                  resMap.put("assigneeRoles",resRolsUserList);
              }
          }
          if(resMap!=null && resMap.size()>0){
              return AjaxResult.success(resMap);
          }
      }
      return AjaxResult.error("没有找到下一个环节办理人");
   }

   /**
    * @Desc: 关闭任务 一般是在我的流程模块中  暂存的流程
    * @auther: landlord
    * @date: 2021/8/10 12:00
    * @return:
    */
   @Override
   @Transactional
   public AjaxResult closeFirstTask(String abwdId){
      if(StrUtil.isEmpty(abwdId)){
          return AjaxResult.error("流程业务ID不存在");
      }
       ActBusWorkflowData actBusWorkflowData =
               actBusWorkflowDataMapper.selectActBusWorkflowDataById(Long.parseLong(abwdId));
      if(actBusWorkflowData==null){
          return AjaxResult.error("流程业务对象不存在");
      }
      String taskId = actBusWorkflowData.getAbwdTaskId();
      Task task =
             taskService.createTaskQuery().taskId(taskId).active().singleResult();
      //删除流程实例
      runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"用户取消");
      //删除历史流程实例
      historyService.deleteHistoricProcessInstance(task.getProcessInstanceId());
      //删除任务 以及历史任务
      taskService.deleteTask(task.getId(),true);
      //删除流程关联数据后再删除流程单据
      actBusArchivesDataService.deleteActBusArchivesDataByAbwdId(actBusWorkflowData.getAbwdId());
      int count =  actBusWorkflowDataMapper.deleteActBusWorkflowDataById(actBusWorkflowData.getAbwdId());
       if(count>0) {
           return AjaxResult.success("流程取消成功");
       }
       else {
           return AjaxResult.error("流程取消失败");
       }

   }

   /**
    * @Desc: 查询所有流程
    * @auther: landlord
    * @date: 2021/8/12 12:26
    * @return:
    */
    @Override
    public List<ActBusWorkflowData> selectProcessMonitoringList(ActBusWorkflowData actBusWorkflowData){
        return actBusWorkflowDataMapper.selectActBusWorkflowDataList(actBusWorkflowData);
    }
    /**
     * @Desc: 中止流程实例
     * @auther: landlord
     * @date: 2021/8/12 15:20
     * @return:
     */
    @Override
    @Transactional
    public AjaxResult stopWorkFlowInstance(String abwdId){
        if(StrUtil.isEmpty(abwdId)){
            return AjaxResult.error("流程业务ID不存在");
        }
        ActBusWorkflowData actBusWorkflowData =
                actBusWorkflowDataMapper.selectActBusWorkflowDataById(Long.parseLong(abwdId));

        if(actBusWorkflowData==null){
            return AjaxResult.error("业务数据不存在或者没有权限操作");
        }

        if(actBusWorkflowData.getAbwdWorkflowStatus() == ActBusWorkFlowStatusEnum.PASS.getKey()){
            return AjaxResult.error("审批通过的流程无法中止");
        }

        if(actBusWorkflowData.getAbwdWorkflowStatus() == ActBusWorkFlowStatusEnum.ENDOFTHEARTIFICIAL.getKey()){
            return AjaxResult.error("流程目前已中止");
        }
        String taskId = actBusWorkflowData.getAbwdTaskId();
        Task task =
                taskService.createTaskQuery().processInstanceId(actBusWorkflowData.getAbwdInstanceId()).active().singleResult();
        //删除流程实例
        runtimeService.deleteProcessInstance(actBusWorkflowData.getAbwdInstanceId(),"人工结束");
        //删除历史流程实例
        //historyService.deleteHistoricProcessInstance(actBusWorkflowData.getAbwdInstanceId());
        //删除任务 以及历史任务
        taskService.deleteTask(task.getId(),false);

        //处理档案业务数据  待处理

        //更新业务数据状态
        ActBusWorkflowData cancelWfData = new ActBusWorkflowData();
        cancelWfData.setAbwdId(Long.parseLong(abwdId));
        cancelWfData.setAbwdWorkflowStatus(ActBusWorkFlowStatusEnum.ENDOFTHEARTIFICIAL.getKey());
        if(actBusWorkflowDataMapper.updateActBusWorkflowData(cancelWfData)>0) {
            actBusArchivesDataService.updateArchivesStatus(Long.parseLong(abwdId), ActOperationTypeEnum.SUSPEND,actBusWorkflowData.getAbwdBusinessType());
            return AjaxResult.success("流程业务中止操作成功");
        }
        else
            return AjaxResult.error("流程业务中止操作失败");

    }


    /**
     * @Desc: 审批驳回后，取消流程操作
     * @auther: landlord
     * @date: 2021/8/12 15:20
     * @return:
     */
    @Override
    @Transactional
    public AjaxResult closeWorkFlowInstance(String abwdId){
        if(StrUtil.isEmpty(abwdId)){
            return AjaxResult.error("流程业务ID不存在");
        }
        ActBusWorkflowData actBusWorkflowData =
                actBusWorkflowDataMapper.selectActBusWorkflowDataById(Long.parseLong(abwdId));

        if(actBusWorkflowData==null){
            return AjaxResult.error("业务数据不存在或者没有权限操作");
        }

        if(actBusWorkflowData.getAbwdWorkflowStatus() == ActBusWorkFlowStatusEnum.PASS.getKey()){
            return AjaxResult.error("审批通过的流程无法取消流程");
        }

        if(actBusWorkflowData.getAbwdWorkflowStatus() == ActBusWorkFlowStatusEnum.CLOSE.getKey()){
            return AjaxResult.error("流程目前已取消");
        }
        String taskId = actBusWorkflowData.getAbwdTaskId();
        Task task =
                taskService.createTaskQuery().processInstanceId(actBusWorkflowData.getAbwdInstanceId()).active().singleResult();
        //删除流程实例
        runtimeService.deleteProcessInstance(actBusWorkflowData.getAbwdInstanceId(),"取消流程");
        //删除历史流程实例
        //historyService.deleteHistoricProcessInstance(actBusWorkflowData.getAbwdInstanceId());
        //删除任务 以及历史任务
        taskService.deleteTask(task.getId(),false);

        //处理档案业务数据  待处理

        //更新业务数据状态
        ActBusWorkflowData cancelWfData = new ActBusWorkflowData();
        cancelWfData.setAbwdId(Long.parseLong(abwdId));
        cancelWfData.setAbwdWorkflowStatus(ActBusWorkFlowStatusEnum.CLOSE.getKey());
        if(actBusWorkflowDataMapper.updateActBusWorkflowData(cancelWfData)>0) {
            actBusArchivesDataService.updateArchivesStatus(Long.parseLong(abwdId), ActOperationTypeEnum.REFUSE,actBusWorkflowData.getAbwdBusinessType());
            return AjaxResult.success("流程业务取消成功");
        }
        else
            return AjaxResult.error("流程业务取消失败");

    }

    /**
     * @Desc: 取消流程发布
     * @auther: landlord
     * @date: 2021/8/17 9:20
     * @return:
     */
    //取消流程发布
    @Override
    public AjaxResult cancelWorkFlow(String abmdId, String deploymentId){
       // 根据部署ID获取正在运行的流程实例
       List<ProcessInstance> listProcessInstance =
               runtimeService.createProcessInstanceQuery().deploymentId(deploymentId).list();
       if(listProcessInstance!=null && listProcessInstance.size()>0){
           return AjaxResult.error("此流程还有正在运行的流程实例,无法取消");
       }
       //修改流程部署状态
        ActBusModelDefinition cancelWfData = new ActBusModelDefinition();
        cancelWfData.setAbmdId(abmdId);
        cancelWfData.setAbmdDeployStatus(ActBusDeployStatusEnum.NO.getKey());
        if(actBusModelDefinitionMapper.updateActBusModelDefinition(cancelWfData)>0)
            return AjaxResult.success("取消流程部署成功");
        else
            return AjaxResult.error("取消流程部署失败");
    }

}
